package io.gitee.hefren.hhconfig.client.service.impl;

import com.google.common.collect.Sets;
import io.gitee.hefren.hhconfig.client.service.ChangeEvent;
import io.gitee.hefren.hhconfig.client.service.HhConfigService;
import org.springframework.cloud.context.environment.EnvironmentChangeEvent;
import org.springframework.context.ApplicationContext;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * @Date 2024/5/29
 * @Author lifei
 */
public class HhConfigServiceImpl implements HhConfigService {

    private Map<String, String> conf = new HashMap<>();
    private ApplicationContext applicationContext;

    public HhConfigServiceImpl(ApplicationContext applicationContext, Map<String, String> conf) {
        this.applicationContext = applicationContext;
        this.conf = conf;
    }

    @Override
    public String[] getPropertyNames() {
        return conf.keySet().toArray(new String[0]);
    }

    @Override
    public String getProperty(String name) {
        return conf.get(name);
    }

    @Override
    public void listener(ChangeEvent changeEvent) {
        Set<String> diffKeys = findDiffKeys(this.conf, changeEvent.getConfigs());
        if (diffKeys.isEmpty()) {
            return;
        }
        this.conf = changeEvent.getConfigs();
        // 通知Spring动态刷新配置
        if (Objects.nonNull(this.conf) && !this.conf.isEmpty()) {
            System.out.println("===> [hhconfig] fire update keys: " + diffKeys);
            applicationContext.publishEvent(new EnvironmentChangeEvent(diffKeys));
        }
    }

    private Set<String> findDiffKeys(Map<String, String> oldConfigs, Map<String, String> newConfigs) {
        Set<String> result = Sets.newHashSet();
        if (mapIsEmpty(oldConfigs) && mapIsEmpty(newConfigs)) {
            return result;
        }else if (mapIsEmpty(oldConfigs) && !mapIsEmpty(newConfigs)) {
            return newConfigs.keySet();
        } else if (!mapIsEmpty(oldConfigs) && mapIsEmpty(newConfigs)) {
            return oldConfigs.keySet();
        }
        Set<String> allKeys = Sets.newHashSet();
        allKeys.addAll(oldConfigs.keySet());
        allKeys.addAll(newConfigs.keySet());
        for (String oneKey : allKeys) {
            if (!oldConfigs.containsKey(oneKey) || !newConfigs.containsKey(oneKey)) {
                result.add(oneKey);
            } else if (!oldConfigs.get(oneKey).equals(newConfigs.get(oneKey))) {
                result.add(oneKey);
            }
        }
        return result;
    }

    private boolean mapIsEmpty(Map<String, String> map) {
        return Objects.isNull(map) || map.isEmpty();
    }
}
